package com.lpf.example.example02.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * netty作为长连接的服务器基于websoket，实现客户端与服务器端长连接。
 */
public class MyServer {

    public static void main(String[] args) throws InterruptedException {

        /**
         * EventLoopGroup底层就是一个死循环，会不停的去准侧底层的输入输出事件，然后对事件进行处理，处理完之后进行任务的执行
         * 任务可能是自己定义的。
         **/

        // 负责接收客户端连接并转发给workerGroup
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 处理连接
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap
                    .group(bossGroup, workerGroup) // 绑定线程池
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))  // 针对bossGroup发挥作用
                    .childHandler(new MyServerInitializer()); // 针对workerGroup发挥作用

            // 绑定端口号
            ChannelFuture channelFuture = serverBootstrap
                    .bind(8899)// 调用这个方法时会通过ChannelFactory创建Channel实例
                    .sync();// sync方法返回时，绑定操作肯定已完成。如果没有sync的话，bind方法会立刻返回，然后执行下面的逻辑，这是由于绑定操作可能没有完成，可能会抛出异常。

            channelFuture
                    .channel()
                    .closeFuture()
                    .sync(); // 服务器端如果关闭的话，要等待关闭完成流程才能往下走。
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}